"""
@author  : MG
@Time    : 2021/7/8 9:19
@File    : upload.py
@contact : mmmaaaggg@163.com
@desc    : 用于将数据自动备份并上传到百度网盘
"""
import hashlib
import json
import os
import threading
from queue import Queue

import requests

# 暂缓实现
# def get_access

class BaiDuUpload():

    def __init__(self):
        self.Q_fileinfo = Queue()
        self.Q_precreat = Queue()
        self.Q_upload = Queue()
        self.Q_create = Queue()
        self.work_dict = {}
        self.upload_path = r"/apps/your app path/"
        self.headers = {
            "User-Agent": "pan.baidu.com",
            "Connection": "keep-alive"

        }
        self.pre_url = "https://pan.baidu.com/rest/2.0/xpan/file?method=precreate&access_token=your_token"
        self.upload_url = "https://d.pcs.baidu.com/rest/2.0/pcs/superfile2?method=upload&access_token=your_token&type=tmpfile"
        self.creat_url = "https://pan.baidu.com/rest/2.0/xpan/file?method=create&access_token=your_token"
        self.part_size = 4 * 1024 * 1024

    def GetMD5FromLocalFile(self, filename):

        file_object = open(filename, 'rb')
        md5_list = []
        while (True):
            file_content = file_object.read(self.part_size)
            if not file_content:
                break
            file_md5 = hashlib.md5(file_content)
            md5_list.append(file_md5.hexdigest())
        file_object.close()
        return md5_list

    def run(self):

        for i in range(10):
            t = threading.Thread(target=self.get_file_info)
            t.setDaemon(True)  # 把子线程设置为守护线程，该线程不重要主线程结束，子线程结束
            t.start()

        for i in range(1):
            t = threading.Thread(target=self.pre_creat)
            t.setDaemon(True)  # 把子线程设置为守护线程，该线程不重要主线程结束，子线程结束
            t.start()

        for i in range(1):
            t = threading.Thread(target=self.upload_file)
            t.setDaemon(True)  # 把子线程设置为守护线程，该线程不重要主线程结束，子线程结束
            t.start()

        for i in range(1):
            t = threading.Thread(target=self.create)
            t.setDaemon(True)  # 把子线程设置为守护线程，该线程不重要主线程结束，子线程结束
            t.start()

        source_folder_name = r'your fold to up load'
        file_list = os.listdir(source_folder_name)

        for file in file_list:
            if not os.path.isdir(file):
                abs_path = os.path.join(source_folder_name, file)
                self.Q_fileinfo.put(abs_path)

        self.Q_fileinfo.join()
        self.Q_precreat.join()
        self.Q_upload.join()
        self.Q_create.join()

    def get_file_info(self):
        while (True):
            file = self.Q_fileinfo.get()
            if not os.path.isdir(file):
                dir, file_name = os.path.split(file)
                file_size = os.path.getsize(file)
                file_path = self.upload_path + file_name
                file_md5list = self.GetMD5FromLocalFile(file)
                self.Q_precreat.put((file, file_name, file_path, file_size, file_md5list))

                # print((file,file_name,file_path,file_size,file_md5list))

            self.Q_fileinfo.task_done()

    def pre_creat(self):
        while (True):
            file, file_name, file_path, file_size, file_md5list = self.Q_precreat.get()

            payload = {'path': file_path,
                       'size': file_size,
                       'rtype': '3',
                       'isdir': '0',
                       'autoinit': '1',
                       'block_list': json.dumps(file_md5list)
                       }
            files = []

            try:
                response = requests.post(self.pre_url, headers=self.headers, data=payload, files=files)
                response_text = response.text.encode('utf8')

                response_dict = json.loads(response_text)
                uploadid = response_dict["uploadid"]
                block_list = response_dict["block_list"]
                print("预上传：", file_name, block_list)

                self.Q_upload.put((file, file_name, file_path, file_size, uploadid, block_list))

            except Exception as result:
                print(file_name, "初始化失败", result)
            self.Q_precreat.task_done()

    def upload_file(self):
        while (True):
            file, file_name, file_path, file_size, uploadid, block_list = self.Q_upload.get()
            md5_list = []
            payload = {}
            targetFile = open(file, 'rb')
            for partseg in block_list:

                url_str = "&path=" + file_path + "&uploadid=" + uploadid + "&partseq=" + str(partseg)
                up_url = self.upload_url + url_str

                files = [
                    ('file', targetFile.read(self.part_size))
                ]

                try:
                    response = requests.post(up_url, headers=self.headers, data=payload, files=files)
                    response_text = response.text.encode('utf8')
                    # print(response_text)
                    response_dict = json.loads(response_text)
                    md5 = response_dict["md5"]
                    print("上传：", file_name, partseg)

                except Exception as result:
                    print(file_name, "上传失败", result)
                    break

                md5_list.append(md5)

            targetFile.close()
            if len(md5_list) == len(block_list):
                self.Q_create.put((file_name, uploadid, file_path, file_size, md5_list))

            self.Q_upload.task_done()

    def create(self):
        while (True):
            file_name, uploadid, file_path, file_size, block_list = self.Q_create.get()

            payload = {'path': file_path,
                       'size': file_size,
                       'rtype': '1',
                       'isdir': '0',
                       'uploadid': uploadid,
                       'block_list': json.dumps(block_list)}
            files = []

            try:
                response = requests.post(self.creat_url, headers=self.headers, data=payload, files=files)
                response_text = response.text.encode('utf8')
                # print(response_text)
                response_dict = json.loads(response_text)
                print("合成：", file_name, response_dict["path"])

            except Exception as result:
                print(file_name, "创建失败", result)

            self.Q_create.task_done()


if __name__ == "__main__":
    bdup = BaiDuUpload()
    bdup.run()
